/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.hd4ic.gui;

import boofcv.abst.feature.detect.edge.DetectEdgeContour;
import boofcv.alg.filter.binary.ThresholdImageOps;
import boofcv.alg.misc.GImageStatistics;
import boofcv.alg.misc.ImageStatistics;
import boofcv.core.image.ConvertBufferedImage;
import boofcv.factory.feature.detect.edge.FactoryDetectEdgeContour;
import boofcv.gui.binary.VisualizeBinaryData;
import boofcv.struct.image.ImageFloat32;
import boofcv.struct.image.ImageSInt16;
import boofcv.struct.image.ImageUInt8;
import com.mortennobel.imagescaling.AdvancedResizeOp;
import com.mortennobel.imagescaling.ResampleOp;
import edu.hd4ic.algorithm.base.HDBasedAlgorithm;
import edu.hd4ic.algorithm.harris.Harris;
import edu.hd4ic.algorithm.realizations.CornerWeightHausdorffDistance;
import edu.hd4ic.algorithm.realizations.GrayImageHausdorffDistance;
import edu.hd4ic.algorithm.realizations.HausdorffDistance;
import edu.hd4ic.algorithm.realizations.M_HausdorffDistance;
import edu.hd4ic.edu.hd4ic.data.CornerAlgorithmParameters;
import edu.hd4ic.edu.hd4ic.data.ProcessingImageDataContainer;
import edu.hd4ic.edu.hd4ic.data.ThresholdEdgeAlgorithmData;
import edu.hd4ic.gui.background.BackGroundSwingWorker;
import edu.hd4ic.gui.background.DefaultHDValuesPresenter;
import edu.hd4ic.gui.controlls.ClearingHistogramThresholdPanel;
import edu.hd4ic.gui.controlls.IconWithDescription;
import edu.hd4ic.gui.controlls.IconWithDescriptionListCellRenderer;
import edu.hd4ic.gui.controlls.ImageTransferHandler;
import georegression.struct.point.Point2D_I32;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.apache.log4j.Logger;

/**
 * @author morfant
 */
public class MainForm extends javax.swing.JFrame {

    public static final Logger LOGGER = Logger.getLogger(MainForm.class);
    private final JFileChooser fileChooser = new JFileChooser();
    private ApplicationData applicationData;
    private String lastOpenedFilePath = "";
    private ProcessingImageDataContainer displayedImageProcessDataContainer = null;
    private Map<String, ProcessingImageDataContainer> inputImageFilePathAndItsDataContainerMap =
            new HashMap<String, ProcessingImageDataContainer>();
    private Map<String, ProcessingImageDataContainer> templateImageFilePathAndItsDataContainerMap =
            new HashMap<String, ProcessingImageDataContainer>();
    private final int ICON_WIDHT = 64;
    private final int ICON_HEIGHT = 64;
    //    private final int NUMBER_OF_
    private ResampleOp resampleOp = new ResampleOp(ICON_WIDHT, ICON_HEIGHT);
    private ClearingHistogramThresholdPanel histogramThresholdPanel = new ClearingHistogramThresholdPanel(256, 256);
    public static final float K_HARRIS_CONST = 1.4f;
    public static final int MIN_MEASUER_HARRIS_CONST = 10;
    public static final int MIN_DISTANCE_HARRIS_CONST = 10;
    public static final int NUM_OF_ITERATION_HARRIS_CONST = 1;
    private Harris harrisCornerDetector =
            new Harris(K_HARRIS_CONST,
                    MIN_MEASUER_HARRIS_CONST,
                    MIN_DISTANCE_HARRIS_CONST,
                    NUM_OF_ITERATION_HARRIS_CONST);

    /**
     * Creates new form MainFrom
     */
    public MainForm() {
        initComponents();
        loadPreviousSession();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        algorithmPanel = new javax.swing.JPanel();
        baseSplitPane = new javax.swing.JSplitPane();
        inputPanel = new javax.swing.JPanel();
        inputDataSplitPane = new javax.swing.JSplitPane();
        inputImagePanel = new javax.swing.JPanel();
        inputImageTabbedPanel = new javax.swing.JTabbedPane();
        inputImageScrollPane = new javax.swing.JScrollPane();
        inputImageLabel = new javax.swing.JLabel();
        edgeScrollPane = new javax.swing.JScrollPane();
        edgeImageLabel = new javax.swing.JLabel();
        relustImageScrollPane = new javax.swing.JScrollPane();
        resultImageLabel = new javax.swing.JLabel();
        cornerScrollPane = new javax.swing.JScrollPane();
        cornerLabel = new javax.swing.JLabel();
        calculatingPanel = new javax.swing.JPanel();
        calculateTabbedPane = new javax.swing.JTabbedPane();
        calculatePanel = new javax.swing.JPanel();
        filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 10), new java.awt.Dimension(0, 10), new java.awt.Dimension(32767, 10));
        computationResultPanel = new javax.swing.JPanel();
        filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767));
        resultsScrollPane = new javax.swing.JScrollPane();
        resultsTextArea = new javax.swing.JTextArea();
        filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 0), new java.awt.Dimension(10, 32767));
        filler4 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 10), new java.awt.Dimension(0, 10), new java.awt.Dimension(32767, 10));
        calculationThresholdPanel = new javax.swing.JPanel();
        calculationThresholdLabel = new javax.swing.JLabel();
        calculationThresholdSpinner = new javax.swing.JSpinner();
        calculateButton = new javax.swing.JButton();
        borderImageCalculatorPanel = new javax.swing.JPanel();
        edgeAlgorimthUsageChechBox = new javax.swing.JPanel();
        isNeedUseEdgeAlgorithm = new javax.swing.JCheckBox();
        edgeAlgorithmChooserPanel = new javax.swing.JPanel();
        edgeAlgorithmTypeComboBox = new javax.swing.JComboBox();
        edgeDetectorsAlgorimthParametersPanel = new javax.swing.JPanel();
        thresholdAlgorithmPanel = new javax.swing.JPanel();
        thresholdHistogrammContainer = new javax.swing.JPanel();
        histogrammLabel = new javax.swing.JLabel();
        histogramContainerPanel = new javax.swing.JPanel();
        thresholdSliderContainer = new javax.swing.JPanel();
        thresholdLabel = new javax.swing.JLabel();
        thresholdSlider = new javax.swing.JSlider();
        cannyAlgorithmPanel = new javax.swing.JPanel();
        cannyHistogrammLabel = new javax.swing.JLabel();
        cannyHistogramConstainerPanel = new javax.swing.JPanel();
        upperThresholdSliderLabel = new javax.swing.JLabel();
        upperThresholdSlider = new javax.swing.JSlider();
        lowerThresholdSliderLabel = new javax.swing.JLabel();
        lowerThresholdSlider = new javax.swing.JSlider();
        cornerSearchPanel = new javax.swing.JPanel();
        kappaParameter = new javax.swing.JPanel();
        kLable = new javax.swing.JLabel();
        filler5 = new javax.swing.Box.Filler(new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 32767));
        kSpinner = new javax.swing.JSpinner();
        filler10 = new javax.swing.Box.Filler(new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 32767));
        minMeasuerParameter = new javax.swing.JPanel();
        minMeasuerLabel = new javax.swing.JLabel();
        filler7 = new javax.swing.Box.Filler(new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 32767));
        minMeasuerSpinner = new javax.swing.JSpinner();
        filler11 = new javax.swing.Box.Filler(new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 32767));
        minDistanceParameter = new javax.swing.JPanel();
        minDistanceLabel = new javax.swing.JLabel();
        filler6 = new javax.swing.Box.Filler(new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 32767));
        minDistanceSpinner = new javax.swing.JSpinner();
        filler12 = new javax.swing.Box.Filler(new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 32767));
        iterationParameter = new javax.swing.JPanel();
        iterationLabel = new javax.swing.JLabel();
        filler8 = new javax.swing.Box.Filler(new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 32767));
        iterationSpinner = new javax.swing.JSpinner();
        jPanel1 = new javax.swing.JPanel();
        calculateCorner = new javax.swing.JButton();
        filler15 = new javax.swing.Box.Filler(new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 0), new java.awt.Dimension(22, 32767));
        sourcePane = new javax.swing.JPanel();
        sourceTabbedPane = new javax.swing.JTabbedPane();
        inputImagesPanel = new javax.swing.JPanel();
        inputImagesScrollPane = new javax.swing.JScrollPane();
        inputImageList = new javax.swing.JList();
        inputImagesControlPanel = new javax.swing.JPanel();
        addInputImageButton = new javax.swing.JButton();
        addFolderWithInputImage = new javax.swing.JButton();
        removeInputImageButton = new javax.swing.JButton();
        templateImagesPanel = new javax.swing.JPanel();
        templateImagesScrollPane = new javax.swing.JScrollPane();
        templateImageList = new javax.swing.JList();
        templateImagesControlPanel = new javax.swing.JPanel();
        addTemplateImageButton = new javax.swing.JButton();
        addFolderWithTemplateImage = new javax.swing.JButton();
        removeTemplateImageButton = new javax.swing.JButton();
        algorithmsPanel = new javax.swing.JPanel();
        algorithmChooserPanel = new javax.swing.JPanel();
        algorithmComboBox = new javax.swing.JComboBox();
        algorithmParametersPanel = new javax.swing.JPanel();
        hdAlgorithmParameters = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        m_hdAlgorithmParameters = new javax.swing.JPanel();
        m_hdThresholdParameterLabel = new javax.swing.JLabel();
        m_hdThresholdParameter = new javax.swing.JSpinner();
        greyImageHDAlgorithmParameters = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        cornerWeightHDAlgorithmParameters = new javax.swing.JPanel();
        jLabel3 = new javax.swing.JLabel();
        weightCornerRadius = new javax.swing.JSpinner();
        jLabel4 = new javax.swing.JLabel();
        weightCornerImportants = new javax.swing.JSpinner();
        menuBar = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        openImageMI = new javax.swing.JMenuItem();
        openTemplateImageMI = new javax.swing.JMenuItem();
        exitMI = new javax.swing.JMenuItem();

        javax.swing.GroupLayout algorithmPanelLayout = new javax.swing.GroupLayout(algorithmPanel);
        algorithmPanel.setLayout(algorithmPanelLayout);
        algorithmPanelLayout.setHorizontalGroup(
            algorithmPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 129, Short.MAX_VALUE)
        );
        algorithmPanelLayout.setVerticalGroup(
            algorithmPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 201, Short.MAX_VALUE)
        );

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setMinimumSize(new java.awt.Dimension(828, 635));
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });
        getContentPane().setLayout(new javax.swing.BoxLayout(getContentPane(), javax.swing.BoxLayout.LINE_AXIS));

        baseSplitPane.setDividerLocation(450);
        baseSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        baseSplitPane.setResizeWeight(0.9);
        baseSplitPane.setPreferredSize(new java.awt.Dimension(332, 346));
        baseSplitPane.setDividerLocation(0.95);

        inputPanel.setPreferredSize(new java.awt.Dimension(100, 100));
        inputPanel.setLayout(new java.awt.GridLayout(1, 0));

        inputDataSplitPane.setDividerLocation(560);
        inputDataSplitPane.setResizeWeight(0.75);
        inputDataSplitPane.setDividerLocation(0.85);

        inputImagePanel.setPreferredSize(new java.awt.Dimension(100, 100));
        inputImagePanel.setLayout(new java.awt.GridLayout(1, 0));

        inputImageTabbedPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Изображение"));

        inputImageLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        inputImageScrollPane.setViewportView(inputImageLabel);

        inputImageTabbedPanel.addTab("Исходное изображение", inputImageScrollPane);

        edgeImageLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        edgeScrollPane.setViewportView(edgeImageLabel);

        inputImageTabbedPanel.addTab("Контурное изображение", edgeScrollPane);

        resultImageLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        relustImageScrollPane.setViewportView(resultImageLabel);

        inputImageTabbedPanel.addTab("Визуальный результат поиска", relustImageScrollPane);

        cornerLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        cornerScrollPane.setViewportView(cornerLabel);

        inputImageTabbedPanel.addTab("Углы", cornerScrollPane);

        inputImagePanel.add(inputImageTabbedPanel);

        inputDataSplitPane.setLeftComponent(inputImagePanel);

        calculatingPanel.setLayout(new java.awt.GridLayout(1, 0));

        calculateTabbedPane.setBorder(javax.swing.BorderFactory.createTitledBorder("Вычисления"));
        calculateTabbedPane.setMinimumSize(new java.awt.Dimension(60, 42));
        calculateTabbedPane.setPreferredSize(new java.awt.Dimension(60, 42));

        calculatePanel.setLayout(new javax.swing.BoxLayout(calculatePanel, javax.swing.BoxLayout.Y_AXIS));
        calculatePanel.add(filler3);

        computationResultPanel.setMinimumSize(new java.awt.Dimension(306, 316));
        computationResultPanel.setPreferredSize(new java.awt.Dimension(306, 216));
        computationResultPanel.setLayout(new javax.swing.BoxLayout(computationResultPanel, javax.swing.BoxLayout.LINE_AXIS));
        computationResultPanel.add(filler1);

        resultsScrollPane.setMinimumSize(new java.awt.Dimension(204, 264));
        resultsScrollPane.setPreferredSize(new java.awt.Dimension(104, 264));

        resultsTextArea.setColumns(20);
        resultsTextArea.setEditable(false);
        resultsTextArea.setRows(5);
        resultsTextArea.setMinimumSize(new java.awt.Dimension(104, 64));
        resultsScrollPane.setViewportView(resultsTextArea);

        computationResultPanel.add(resultsScrollPane);
        computationResultPanel.add(filler2);

        calculatePanel.add(computationResultPanel);
        calculatePanel.add(filler4);

        calculationThresholdPanel.setMinimumSize(new java.awt.Dimension(109, 20));
        calculationThresholdPanel.setPreferredSize(new java.awt.Dimension(109, 20));
        calculationThresholdPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.CENTER, 20, 5));

        calculationThresholdLabel.setText("Порог вычислений:");
        calculationThresholdPanel.add(calculationThresholdLabel);

        calculationThresholdSpinner.setModel(new javax.swing.SpinnerNumberModel(0.0d, 0.0d, 100.0d, 0.1d));
        calculationThresholdPanel.add(calculationThresholdSpinner);

        calculateButton.setText("Вычислить");
        calculateButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                calculateButtonActionPerformed(evt);
            }
        });
        calculationThresholdPanel.add(calculateButton);

        calculatePanel.add(calculationThresholdPanel);

        calculateTabbedPane.addTab("Вычислить", calculatePanel);

        borderImageCalculatorPanel.setMinimumSize(new java.awt.Dimension(230, 0));
        borderImageCalculatorPanel.setPreferredSize(new java.awt.Dimension(230, 377));

        isNeedUseEdgeAlgorithm.setText("Искать контура");
        isNeedUseEdgeAlgorithm.setEnabled(false);
        isNeedUseEdgeAlgorithm.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                isNeedUseEdgeAlgorithmActionPerformed(evt);
            }
        });
        edgeAlgorimthUsageChechBox.add(isNeedUseEdgeAlgorithm);

        edgeAlgorithmChooserPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Алгоритм поиска границ"));
        edgeAlgorithmChooserPanel.setPreferredSize(new java.awt.Dimension(201, 100));

        edgeAlgorithmTypeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Пороговый", "Канни", "Динамический Канни" }));
        edgeAlgorithmTypeComboBox.setEnabled(false);
        edgeAlgorithmTypeComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                edgeAlgorithmTypeComboBoxActionPerformed(evt);
            }
        });
        edgeAlgorithmChooserPanel.add(edgeAlgorithmTypeComboBox);

        edgeDetectorsAlgorimthParametersPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Параметры алгоритма"));
        edgeDetectorsAlgorimthParametersPanel.setLayout(new java.awt.CardLayout());

        thresholdAlgorithmPanel.setMinimumSize(new java.awt.Dimension(237, 147));
        thresholdAlgorithmPanel.setPreferredSize(new java.awt.Dimension(237, 138));
        java.awt.FlowLayout flowLayout1 = new java.awt.FlowLayout();
        flowLayout1.setAlignOnBaseline(true);
        thresholdAlgorithmPanel.setLayout(flowLayout1);

        thresholdHistogrammContainer.setLayout(new java.awt.BorderLayout());

        histogrammLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        histogrammLabel.setText("Гистограмма");
        histogrammLabel.setPreferredSize(new java.awt.Dimension(200, 14));
        thresholdHistogrammContainer.add(histogrammLabel, java.awt.BorderLayout.NORTH);

        histogramContainerPanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        histogramContainerPanel.setMinimumSize(new java.awt.Dimension(60, 100));
        histogramContainerPanel.setPreferredSize(new java.awt.Dimension(200, 100));
        histogramContainerPanel.setLayout(new javax.swing.BoxLayout(histogramContainerPanel, javax.swing.BoxLayout.LINE_AXIS));
        histogramContainerPanel.add(histogramThresholdPanel);
        thresholdHistogrammContainer.add(histogramContainerPanel, java.awt.BorderLayout.PAGE_END);

        thresholdAlgorithmPanel.add(thresholdHistogrammContainer);

        thresholdSliderContainer.setLayout(new java.awt.BorderLayout());

        thresholdLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        thresholdLabel.setText("Порог");
        thresholdLabel.setPreferredSize(new java.awt.Dimension(200, 14));
        thresholdSliderContainer.add(thresholdLabel, java.awt.BorderLayout.CENTER);

        thresholdSlider.setMajorTickSpacing(10);
        thresholdSlider.setMaximum(255);
        thresholdSlider.setMinorTickSpacing(1);
        thresholdSlider.setPaintTicks(true);
        thresholdSlider.setSnapToTicks(true);
        thresholdSlider.setValue(0);
        thresholdSlider.setEnabled(false);
        thresholdSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                thresholdSliderStateChanged(evt);
            }
        });
        thresholdSliderContainer.add(thresholdSlider, java.awt.BorderLayout.PAGE_END);

        thresholdAlgorithmPanel.add(thresholdSliderContainer);

        edgeDetectorsAlgorimthParametersPanel.add(thresholdAlgorithmPanel, "thresholdAlgorithm");

        cannyHistogrammLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        cannyHistogrammLabel.setText("Гистограмма");
        cannyHistogrammLabel.setPreferredSize(new java.awt.Dimension(200, 14));
        cannyAlgorithmPanel.add(cannyHistogrammLabel);

        cannyHistogramConstainerPanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
        cannyHistogramConstainerPanel.setMinimumSize(new java.awt.Dimension(60, 100));
        cannyHistogramConstainerPanel.setPreferredSize(new java.awt.Dimension(200, 100));
        cannyHistogramConstainerPanel.setLayout(new javax.swing.BoxLayout(cannyHistogramConstainerPanel, javax.swing.BoxLayout.LINE_AXIS));
        cannyAlgorithmPanel.add(cannyHistogramConstainerPanel);

        upperThresholdSliderLabel.setText("Верхняя граница");
        cannyAlgorithmPanel.add(upperThresholdSliderLabel);

        upperThresholdSlider.setMajorTickSpacing(10);
        upperThresholdSlider.setMaximum(255);
        upperThresholdSlider.setMinorTickSpacing(1);
        upperThresholdSlider.setPaintTicks(true);
        upperThresholdSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                upperThresholdSliderStateChanged(evt);
            }
        });
        cannyAlgorithmPanel.add(upperThresholdSlider);

        lowerThresholdSliderLabel.setText("Нижняя граница");
        cannyAlgorithmPanel.add(lowerThresholdSliderLabel);

        lowerThresholdSlider.setMajorTickSpacing(10);
        lowerThresholdSlider.setMaximum(255);
        lowerThresholdSlider.setMinorTickSpacing(1);
        lowerThresholdSlider.setPaintTicks(true);
        lowerThresholdSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                lowerThresholdSliderStateChanged(evt);
            }
        });
        cannyAlgorithmPanel.add(lowerThresholdSlider);

        edgeDetectorsAlgorimthParametersPanel.add(cannyAlgorithmPanel, "cannyAlgorithm");

        javax.swing.GroupLayout borderImageCalculatorPanelLayout = new javax.swing.GroupLayout(borderImageCalculatorPanel);
        borderImageCalculatorPanel.setLayout(borderImageCalculatorPanelLayout);
        borderImageCalculatorPanelLayout.setHorizontalGroup(
            borderImageCalculatorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(edgeDetectorsAlgorimthParametersPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
            .addGroup(borderImageCalculatorPanelLayout.createSequentialGroup()
                .addComponent(edgeAlgorithmChooserPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 334, Short.MAX_VALUE)
                .addGap(4, 4, 4))
            .addComponent(edgeAlgorimthUsageChechBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        borderImageCalculatorPanelLayout.setVerticalGroup(
            borderImageCalculatorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(borderImageCalculatorPanelLayout.createSequentialGroup()
                .addComponent(edgeAlgorimthUsageChechBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(edgeAlgorithmChooserPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 58, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(edgeDetectorsAlgorimthParametersPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE))
        );

        calculateTabbedPane.addTab("Поиск контуров", borderImageCalculatorPanel);

        cornerSearchPanel.setLayout(new javax.swing.BoxLayout(cornerSearchPanel, javax.swing.BoxLayout.PAGE_AXIS));

        kappaParameter.setLayout(new javax.swing.BoxLayout(kappaParameter, javax.swing.BoxLayout.X_AXIS));

        kLable.setText("K");
        kappaParameter.add(kLable);
        kappaParameter.add(filler5);

        kSpinner.setModel(new javax.swing.SpinnerNumberModel(Float.valueOf(1.4f), Float.valueOf(0.0f), Float.valueOf(100.0f), Float.valueOf(0.1f)));
        kSpinner.setMaximumSize(new java.awt.Dimension(60, 20));
        kSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                kSpinnerStateChanged(evt);
            }
        });
        kappaParameter.add(kSpinner);

        cornerSearchPanel.add(kappaParameter);
        cornerSearchPanel.add(filler10);

        minMeasuerParameter.setLayout(new javax.swing.BoxLayout(minMeasuerParameter, javax.swing.BoxLayout.X_AXIS));

        minMeasuerLabel.setText("Минимальная мера");
        minMeasuerParameter.add(minMeasuerLabel);
        minMeasuerParameter.add(filler7);

        minMeasuerSpinner.setModel(new javax.swing.SpinnerNumberModel(10, 1, 100, 1));
        minMeasuerSpinner.setMaximumSize(new java.awt.Dimension(60, 20));
        minMeasuerSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                minMeasuerSpinnerStateChanged(evt);
            }
        });
        minMeasuerParameter.add(minMeasuerSpinner);

        cornerSearchPanel.add(minMeasuerParameter);
        cornerSearchPanel.add(filler11);

        minDistanceParameter.setLayout(new javax.swing.BoxLayout(minDistanceParameter, javax.swing.BoxLayout.X_AXIS));

        minDistanceLabel.setText("Минимальная дистанция");
        minDistanceParameter.add(minDistanceLabel);
        minDistanceParameter.add(filler6);

        minDistanceSpinner.setModel(new javax.swing.SpinnerNumberModel(10, 1, 100, 1));
        minDistanceSpinner.setMaximumSize(new java.awt.Dimension(60, 20));
        minDistanceSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                minDistanceSpinnerStateChanged(evt);
            }
        });
        minDistanceParameter.add(minDistanceSpinner);

        cornerSearchPanel.add(minDistanceParameter);
        cornerSearchPanel.add(filler12);

        iterationParameter.setLayout(new javax.swing.BoxLayout(iterationParameter, javax.swing.BoxLayout.X_AXIS));

        iterationLabel.setText("Число итераций");
        iterationParameter.add(iterationLabel);
        iterationParameter.add(filler8);

        iterationSpinner.setModel(new javax.swing.SpinnerNumberModel(1, 1, 100, 1));
        iterationSpinner.setMaximumSize(new java.awt.Dimension(60, 20));
        iterationSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                iterationSpinnerStateChanged(evt);
            }
        });
        iterationParameter.add(iterationSpinner);

        cornerSearchPanel.add(iterationParameter);

        jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, javax.swing.BoxLayout.LINE_AXIS));

        calculateCorner.setText("Вычислить");
        calculateCorner.setEnabled(false);
        calculateCorner.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                calculateCornerActionPerformed(evt);
            }
        });
        jPanel1.add(calculateCorner);

        cornerSearchPanel.add(jPanel1);
        cornerSearchPanel.add(filler15);

        calculateTabbedPane.addTab("Поиск точек интереса", cornerSearchPanel);

        calculatingPanel.add(calculateTabbedPane);

        inputDataSplitPane.setRightComponent(calculatingPanel);

        inputPanel.add(inputDataSplitPane);

        baseSplitPane.setLeftComponent(inputPanel);

        sourcePane.setPreferredSize(new java.awt.Dimension(100, 100));
        sourcePane.setLayout(new java.awt.GridLayout(1, 0));

        sourceTabbedPane.setBorder(javax.swing.BorderFactory.createTitledBorder("Исходные данные"));
        sourceTabbedPane.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                sourceTabbedPaneStateChanged(evt);
            }
        });

        inputImagesPanel.setLayout(new javax.swing.BoxLayout(inputImagesPanel, javax.swing.BoxLayout.LINE_AXIS));

        inputImagesScrollPane.setBorder(javax.swing.BorderFactory.createTitledBorder("Изображения"));

        inputImageList.setModel(new DefaultListModel());
        inputImageList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        inputImageList.setCellRenderer(new IconWithDescriptionListCellRenderer(20));
        inputImageList.setDragEnabled(true);
        inputImageList.setDropMode(javax.swing.DropMode.INSERT);
        inputImageList.setLayoutOrientation(javax.swing.JList.HORIZONTAL_WRAP);
        inputImageList.setTransferHandler(new ImageTransferHandler(inputImageList));
        inputImageList.setVisibleRowCount(-1);
        inputImageList.setDragEnabled(true);
        inputImageList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {public void valueChanged(ListSelectionEvent event){inputImageListSelectionChanged(event);}});
        inputImagesScrollPane.setViewportView(inputImageList);

        inputImagesPanel.add(inputImagesScrollPane);

        inputImagesControlPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Управление изображениями"));
        inputImagesControlPanel.setMaximumSize(new java.awt.Dimension(3003, 3127));
        inputImagesControlPanel.setMinimumSize(new java.awt.Dimension(280, 127));
        inputImagesControlPanel.setPreferredSize(new java.awt.Dimension(280, 127));

        addInputImageButton.setText("Добавить исследуемое изобарежние");
        addInputImageButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addInputImageButtonActionPerformed(evt);
            }
        });
        inputImagesControlPanel.add(addInputImageButton);

        addFolderWithInputImage.setText("Добавить папку");
        addFolderWithInputImage.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addFolderWithInputImageActionPerformed(evt);
            }
        });
        inputImagesControlPanel.add(addFolderWithInputImage);

        removeInputImageButton.setText("Убрать исследуемое изображение");
        removeInputImageButton.setToolTipText("");
        removeInputImageButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeInputImageButtonActionPerformed(evt);
            }
        });
        inputImagesControlPanel.add(removeInputImageButton);

        inputImagesPanel.add(inputImagesControlPanel);

        sourceTabbedPane.addTab("Исследуемые изображения", inputImagesPanel);

        templateImagesPanel.setLayout(new javax.swing.BoxLayout(templateImagesPanel, javax.swing.BoxLayout.LINE_AXIS));

        templateImagesScrollPane.setBorder(javax.swing.BorderFactory.createTitledBorder("Шаблоны"));

        templateImageList.setModel(new DefaultListModel());
        templateImageList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        templateImageList.setCellRenderer(new IconWithDescriptionListCellRenderer(20));
        templateImageList.setDragEnabled(true);
        templateImageList.setDropMode(javax.swing.DropMode.INSERT);
        templateImageList.setLayoutOrientation(javax.swing.JList.HORIZONTAL_WRAP);
        templateImageList.setTransferHandler(new ImageTransferHandler(templateImageList));
        templateImageList.setVisibleRowCount(-1);
        templateImageList.setDragEnabled(true);

        templateImageList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {

            public void valueChanged(ListSelectionEvent event) {
                templateImageListSelectionChanged(event);
            }
        });
        templateImagesScrollPane.setViewportView(templateImageList);

        templateImagesPanel.add(templateImagesScrollPane);

        templateImagesControlPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Управление шаблонами"));
        templateImagesControlPanel.setMaximumSize(new java.awt.Dimension(3003, 3127));
        templateImagesControlPanel.setMinimumSize(new java.awt.Dimension(280, 127));
        templateImagesControlPanel.setPreferredSize(new java.awt.Dimension(280, 127));

        addTemplateImageButton.setText("Добавить шаблонное изобарежния");
        addTemplateImageButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addTemplateImageButtonActionPerformed(evt);
            }
        });
        templateImagesControlPanel.add(addTemplateImageButton);

        addFolderWithTemplateImage.setText("Добавить папку");
        addFolderWithTemplateImage.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addFolderWithTemplateImageActionPerformed(evt);
            }
        });
        templateImagesControlPanel.add(addFolderWithTemplateImage);

        removeTemplateImageButton.setText("Убрать шаблонное изображение");
        removeTemplateImageButton.setToolTipText("");
        removeTemplateImageButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeTemplateImageButtonActionPerformed(evt);
            }
        });
        templateImagesControlPanel.add(removeTemplateImageButton);

        templateImagesPanel.add(templateImagesControlPanel);

        sourceTabbedPane.addTab("Шаблонные изображения", templateImagesPanel);

        algorithmsPanel.setLayout(new javax.swing.BoxLayout(algorithmsPanel, javax.swing.BoxLayout.LINE_AXIS));

        algorithmChooserPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Алгоритм"));
        algorithmChooserPanel.setPreferredSize(new java.awt.Dimension(120, 57));

        algorithmComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "HD", "M-HD", "NHD", "SWHD" }));
        algorithmComboBox.setMinimumSize(new java.awt.Dimension(98, 20));
        algorithmComboBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                algorithmComboBoxActionPerformed(evt);
            }
        });
        algorithmChooserPanel.add(algorithmComboBox);

        algorithmsPanel.add(algorithmChooserPanel);

        algorithmParametersPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Параметры алгоритма"));
        algorithmParametersPanel.setMinimumSize(new java.awt.Dimension(300, 100));
        algorithmParametersPanel.setPreferredSize(new java.awt.Dimension(500, 100));
        algorithmParametersPanel.setLayout(new java.awt.CardLayout());

        jLabel1.setText("Для этого алгоритма нет параметров.");
        hdAlgorithmParameters.add(jLabel1);

        algorithmParametersPanel.add(hdAlgorithmParameters, "hdAlgorithmParameters");

        m_hdAlgorithmParameters.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        m_hdThresholdParameterLabel.setText("Порог поиска по фону");
        m_hdAlgorithmParameters.add(m_hdThresholdParameterLabel);

        m_hdThresholdParameter.setModel(new javax.swing.SpinnerNumberModel(3, 0, 256, 1));
        m_hdAlgorithmParameters.add(m_hdThresholdParameter);

        algorithmParametersPanel.add(m_hdAlgorithmParameters, "m_hdAlgorithmParameters");

        jLabel2.setText("Для этого алгоритма нет параметров.");
        greyImageHDAlgorithmParameters.add(jLabel2);

        algorithmParametersPanel.add(greyImageHDAlgorithmParameters, "greyImageHDAlgorithmParameters");

        cornerWeightHDAlgorithmParameters.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        jLabel3.setText("Радиус дествия весовой функции");
        cornerWeightHDAlgorithmParameters.add(jLabel3);

        weightCornerRadius.setModel(new javax.swing.SpinnerNumberModel(2, 0, 100, 1));
        cornerWeightHDAlgorithmParameters.add(weightCornerRadius);

        jLabel4.setText("Степень важности зоны точки интереса");
        cornerWeightHDAlgorithmParameters.add(jLabel4);

        weightCornerImportants.setModel(new javax.swing.SpinnerNumberModel(2, 2, 100, 1));
        cornerWeightHDAlgorithmParameters.add(weightCornerImportants);

        algorithmParametersPanel.add(cornerWeightHDAlgorithmParameters, "weightCornerHDAlgorithm");

        algorithmsPanel.add(algorithmParametersPanel);

        sourceTabbedPane.addTab("Алгоритмы", algorithmsPanel);

        sourcePane.add(sourceTabbedPane);

        baseSplitPane.setRightComponent(sourcePane);

        getContentPane().add(baseSplitPane);

        fileMenu.setText("Файл");

        openImageMI.setText("Открыть изображение");
        openImageMI.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openImageMIActionPerformed(evt);
            }
        });
        fileMenu.add(openImageMI);

        openTemplateImageMI.setText("Открыть шаблонное изображение");
        openTemplateImageMI.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openTemplateImageMIActionPerformed(evt);
            }
        });
        fileMenu.add(openTemplateImageMI);

        exitMI.setText("Выход");
        fileMenu.add(exitMI);

        menuBar.add(fileMenu);

        setJMenuBar(menuBar);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private File loadImageFileFromFileSystem() {
        if (!"".equals(lastOpenedFilePath)) {
            fileChooser.setCurrentDirectory(new File(lastOpenedFilePath));
        }
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        int returnValue = fileChooser.showOpenDialog(this);
        if (returnValue == JFileChooser.APPROVE_OPTION) {
            File imageFile = fileChooser.getSelectedFile();
            lastOpenedFilePath = imageFile.getPath();
            return imageFile;
        } else {
            LOGGER.debug("Открытие файла отменено пользователем.");
            return null;
        }
    }

    private File loadImageDirectoryFileFromFileSystem() {
        if (!"".equals(lastOpenedFilePath)) {
            fileChooser.setCurrentDirectory(new File(lastOpenedFilePath));
        }
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int returnValue = fileChooser.showOpenDialog(this);
        if (returnValue == JFileChooser.APPROVE_OPTION) {
            File imageFile = fileChooser.getSelectedFile();
            lastOpenedFilePath = imageFile.getPath();
            return imageFile;
        } else {
            LOGGER.debug("Открытие файла отменено пользователем.");
            return null;
        }
    }

    private File loadImageFileFromFilePath(String filePath) {
        File imageFile = new File(filePath);
        return imageFile;
    }

    private void showErrorDialog(String errorMessage) {
        JOptionPane.showMessageDialog(this, errorMessage, "Ошибка!", JOptionPane.ERROR_MESSAGE);
    }

    private void showInformationDialog(String informationMessage) {
        JOptionPane.showMessageDialog(this, informationMessage, "Внимание!", JOptionPane.INFORMATION_MESSAGE);
    }

    public static BufferedImage binarization(BufferedImage image) {
        // convert into a usable format
        ImageFloat32 input = ConvertBufferedImage.convertFromSingle(image, null, ImageFloat32.class);
        ImageUInt8 binary = new ImageUInt8(input.width, input.height);

        // the mean pixel value is often a reasonable threshold when creating a binary image
        float mean = (float) ImageStatistics.mean(input);

        // create a binary image
        ThresholdImageOps.threshold(input, binary, mean, true);

        // Render the binary image for output and display it in a window
        BufferedImage visualBinary = VisualizeBinaryData.renderBinary(binary, null);
        return visualBinary;
    }

    public static BufferedImage binaryExample(BufferedImage image,int threshold) {
        // convert into a usable format
        ImageFloat32 input = ConvertBufferedImage.convertFromSingle(image, null, ImageFloat32.class);
        ImageUInt8 binary = new ImageUInt8(input.width, input.height);

        // the mean pixel value is often a reasonable threshold when creating a binary image
//        int mean = (int) ImageStatistics.mean(input);

        // create a binary image
        ThresholdImageOps.threshold(input, binary, threshold, true);

        // Render the binary image for output and display it in a window
        BufferedImage visualBinary = VisualizeBinaryData.renderBinary(binary, null);
        return visualBinary;
//        ShowImages.showWindow(visualBinary, "Binary Image");
    }

    private void loadPreviousSession() {
        histogramThresholdPanel.clearHistogramm();
        histogramContainerPanel.repaint();
        applicationData = new ApplicationData();
        lastOpenedFilePath = applicationData.getLastFilePath();
        try {
            Map<String, Integer> inputImageFilePathWithThreshold = applicationData.getInputImageFilePathWitThresholdMap();
            Map<String, Integer> templateImageFilePathWithThreshold = applicationData.getTemplateImageFilePathWitThresholdMap();
            Map<String, String[]> templateImageFilePathWithCornerParameters = applicationData.getTemplateImageFilePathWithCornerParameters();
            Integer threshold = null;
            ProcessingImageDataContainer processingImageDataContainer;
            String[] cornerParameters;
            float kappa;
            int minMeasuer, minDistance, iterationNumber;
            for (String inputImageFilePath : inputImageFilePathWithThreshold.keySet()) {
                addInputImage(loadImageFileFromFilePath(inputImageFilePath));
                threshold = inputImageFilePathWithThreshold.get(inputImageFilePath);
                if (threshold != null) {
                    processingImageDataContainer = inputImageFilePathAndItsDataContainerMap.get(inputImageFilePath);
                    processingImageDataContainer.setThresholdEdgeAlgorithmData(new ThresholdEdgeAlgorithmData(threshold));
                    processingImageDataContainer.setEdgeInputImage(
                            createEdgeImageFromInputImageByThreshold(
                                    (BufferedImage) processingImageDataContainer.getInputImage(),
                                    threshold));
                    processingImageDataContainer = inputImageFilePathAndItsDataContainerMap.get(inputImageFilePath);
//                    ImageIO.write(binaryExample((BufferedImage) processingImageDataContainer.getInputImage(),threshold),
//                            "bmp",
//                            new File(inputImageFilePath.substring(0, inputImageFilePath.lastIndexOf("."))
//                                    + "_bin"
//                                    + ".bmp"));
                }

            }
            for (String templateImageFilePath : templateImageFilePathWithThreshold.keySet()) {
                addTemplateImage(loadImageFileFromFilePath(templateImageFilePath));
                threshold = templateImageFilePathWithThreshold.get(templateImageFilePath);
                cornerParameters = templateImageFilePathWithCornerParameters.get(templateImageFilePath);
                if (threshold != null) {
                    processingImageDataContainer = templateImageFilePathAndItsDataContainerMap.get(templateImageFilePath);
                    processingImageDataContainer.setThresholdEdgeAlgorithmData(new ThresholdEdgeAlgorithmData(threshold));
                    processingImageDataContainer.setEdgeInputImage(
                            createEdgeImageFromInputImageByThreshold(
                                    (BufferedImage) processingImageDataContainer.getInputImage(),
                                    threshold));
//                    ImageIO.write((BufferedImage)processingImageDataContainer.getEdgeInputImage(),
//                            "bmp",
//                            new File(templateImageFilePath.substring(0,templateImageFilePath.lastIndexOf("."))
//                                    +"_edge"
//                                    +".bmp"));
                    if (cornerParameters != null) {
                        if (cornerParameters[0] == null) {
                            continue;
                        }
                        kappa = Float.valueOf(cornerParameters[0]);
                        minMeasuer = Integer.valueOf(cornerParameters[1]);
                        minDistance = Integer.valueOf(cornerParameters[2]);
                        iterationNumber = Integer.valueOf(cornerParameters[3]);
                        harrisCornerDetector.setGaussiansigma(kappa);
                        harrisCornerDetector.setMinMeasure(minMeasuer);
                        harrisCornerDetector.setMinDistance(minDistance);
                        harrisCornerDetector.setPiramidi(iterationNumber);
                        processingImageDataContainer.setCornerImage(harrisCornerDetector.process((BufferedImage) processingImageDataContainer.getEdgeInputImage()));
                        processingImageDataContainer.setCorners(harrisCornerDetector.lastProcessResult());
                        processingImageDataContainer.
                                setCornerAlgorithmParameters(new CornerAlgorithmParameters(iterationNumber, kappa, minDistance, minMeasuer));
                    }
                }
            }
        } catch (IOException ex) {
            LOGGER.error("Ошибки при загрузке предыдущей конфигурации!", ex);
        }
    }

    private BufferedImage createEdgeImageFromInputImageByCanny(BufferedImage inputImage, double lowerThreshold, double upperThreshold, boolean dynamic) {
        ImageUInt8 gray = ConvertBufferedImage.convertFrom(inputImage, (ImageUInt8) null);
        DetectEdgeContour<ImageUInt8> cannyD =
                FactoryDetectEdgeContour.canny(lowerThreshold, upperThreshold, dynamic, ImageUInt8.class, ImageSInt16.class);
        cannyD.process(gray);
        List<List<Point2D_I32>> edges = cannyD.getContours();
        BufferedImage output = new BufferedImage(gray.width, gray.height, BufferedImage.TYPE_BYTE_GRAY);
        for (List<Point2D_I32> l : edges) {
            for (Point2D_I32 p : l) {
                output.setRGB(p.x, p.y, 0xFFFFF);
            }
        }
        return output;
    }

    private BufferedImage createEdgeImageFromInputImageByThreshold(BufferedImage inputImage, double threshold) {
        ImageUInt8 gray = ConvertBufferedImage.convertFrom(inputImage, (ImageUInt8) null);
        DetectEdgeContour<ImageUInt8> simple =
                FactoryDetectEdgeContour.binarySimple(threshold, true);
        simple.process(gray);
        List<List<Point2D_I32>> edges = simple.getContours();
        BufferedImage output = new BufferedImage(gray.width, gray.height, BufferedImage.TYPE_BYTE_GRAY);
        for (List<Point2D_I32> l : edges) {
            for (Point2D_I32 p : l) {
                output.setRGB(p.x, p.y, 0xFFFFF);
            }
        }
        return output;
    }

    private void addInputImage(File imageFile) throws IOException {
        LOGGER.debug("Открытие файла: " + imageFile.getName() + ".");
        try {
            BufferedImage inputImage = ImageIO.read(imageFile);
            ResampleOp resizeImage = new ResampleOp(ICON_WIDHT, ICON_HEIGHT);
            ((DefaultListModel) inputImageList.getModel()).addElement(new IconWithDescription(new ImageIcon(resizeImage.filter(inputImage, null)),
                    imageFile.getPath()));
            inputImageFilePathAndItsDataContainerMap.put(imageFile.getPath(), new ProcessingImageDataContainer(inputImage));
        } catch (IOException ex) {
            LOGGER.error("Ошибка при открытие файла с изображением.", ex);
            throw ex;
        }
    }

    private void addTemplateImage(File imageFile) throws IOException {
        try {
            BufferedImage inputImage = ImageIO.read(imageFile);
            ResampleOp resizeImage = new ResampleOp(ICON_WIDHT, ICON_HEIGHT);
            ((DefaultListModel) templateImageList.getModel()).addElement(new IconWithDescription(new ImageIcon(resizeImage.filter(inputImage, null)),
                    imageFile.getPath()));
            templateImageFilePathAndItsDataContainerMap.put(imageFile.getPath(), new ProcessingImageDataContainer(inputImage));
        } catch (IOException ex) {
            LOGGER.error("Ошибка при открытие файла с изображением.", ex);
            throw ex;
        }
    }

    private void removeTemplateImage() {
        int selectedItemIndex = templateImageList.getSelectedIndex();
        if (selectedItemIndex != -1) {
            IconWithDescription deleteItem = (IconWithDescription) templateImageList.getSelectedValue();
            templateImageFilePathAndItsDataContainerMap.remove(deleteItem.getDescription());
            ((DefaultListModel) templateImageList.getModel()).remove(selectedItemIndex);
        } else {
            showInformationDialog("Выбере шаблонное изображение для удаления!");
        }
    }

    private void removeInputImage() {
        int selectedItemIndex = inputImageList.getSelectedIndex();
        if (selectedItemIndex != -1) {
            IconWithDescription deleteItem = (IconWithDescription) inputImageList.getSelectedValue();
            inputImageFilePathAndItsDataContainerMap.remove(deleteItem.getDescription());
            ((DefaultListModel) inputImageList.getModel()).remove(selectedItemIndex);
            inputImageLabel.setIcon(null);
            edgeImageLabel.setIcon(null);
            isNeedUseEdgeAlgorithm.setEnabled(false);
            isNeedUseEdgeAlgorithm.setSelected(false);
            thresholdSlider.setEnabled(false);
            thresholdSlider.setValue(0);
            histogramThresholdPanel.clearHistogramm();
            histogramThresholdPanel.repaint();
        } else {
            showInformationDialog("Выбере входное изображение для удаления!");
        }
    }

    private void openImageMIActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openImageMIActionPerformed
        try {
            File file = loadImageFileFromFileSystem();
            if (file != null) {
                addInputImage(file);
            }
        } catch (IOException ex) {
            showErrorDialog("Ошибка при открытии изображения для распознования!");
        }
    }//GEN-LAST:event_openImageMIActionPerformed

    private List<Image> getInputImageForProcessing(Collection<ProcessingImageDataContainer> inputImageForProcessingDataContainer) {
        List<Image> output = new LinkedList<Image>();
        Image edgeImage;

        for (ProcessingImageDataContainer imageDataContainer : inputImageForProcessingDataContainer) {
            edgeImage = imageDataContainer.getEdgeInputImage();
            if (edgeImage != null) {
                output.add(edgeImage);
            } else {
                output.add(imageDataContainer.getInputImage());
            }
        }

        return output;
    }

    private HDBasedAlgorithm getHDBasedAlgorithmForCalculation() {
        HDBasedAlgorithm hDBasedAlgorithm = null;
        String algorithmName = (String) algorithmComboBox.getSelectedItem();
        if ("HD".equals(algorithmName)) {
            hDBasedAlgorithm = new HausdorffDistance();
        }
        if ("M-HD".equals(algorithmName)) {
            hDBasedAlgorithm = new M_HausdorffDistance((Integer) m_hdThresholdParameter.getValue());
        }
        if ("NHD".equals(algorithmName)) {
            hDBasedAlgorithm = new GrayImageHausdorffDistance();
        }
        if ("SWHD".equals(algorithmName)) {
            hDBasedAlgorithm =
                    new CornerWeightHausdorffDistance((Integer) weightCornerRadius.getValue(),
                            (Integer) weightCornerImportants.getValue());
        }
        if (hDBasedAlgorithm == null) {
            throw new RuntimeException("Подходящий алгоритм не выбран!!!");
        }
        return hDBasedAlgorithm;
    }

    private void calculateButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_calculateButtonActionPerformed
        if ((!inputImageFilePathAndItsDataContainerMap.isEmpty())
                && (!templateImageFilePathAndItsDataContainerMap.isEmpty())) {
            calculateButton.setEnabled(false);
            int selectedIndex = sourceTabbedPane.getSelectedIndex();
            JList imageList = null;
            if (selectedIndex != 1) {
                imageList = inputImageList;
            }
            (new BackGroundSwingWorker(getHDBasedAlgorithmForCalculation(),
                    (Double) calculationThresholdSpinner.getValue(),
                    inputImageFilePathAndItsDataContainerMap,
                    templateImageFilePathAndItsDataContainerMap,
                    new DefaultHDValuesPresenter(calculateButton,
                            resultsTextArea,
                            inputImageFilePathAndItsDataContainerMap,
                            templateImageFilePathAndItsDataContainerMap,
                            imageList))).execute();
        } else {
            showInformationDialog("Для распознования должны присутствовать шаблонные и входные изображения!");
        }
    }//GEN-LAST:event_calculateButtonActionPerformed

    private Map<String, Integer> convertMapWithFilePathAndProcessImageDataContainerInToStorableFormat(Map<String, ProcessingImageDataContainer> convertMap) {
        Map<String, Integer> imageFilePathWithThreshold = new HashMap<String, Integer>();
        ThresholdEdgeAlgorithmData thresholdEdgeAlgorithmData;
        for (String filePath : convertMap.keySet()) {
            thresholdEdgeAlgorithmData = convertMap.get(filePath).getThresholdEdgeAlgorithmData();
            imageFilePathWithThreshold.put(filePath,
                    thresholdEdgeAlgorithmData != null
                            ? thresholdEdgeAlgorithmData.getThreshold()
                            : null);
        }
        return imageFilePathWithThreshold;
    }

    private Map<String, String[]> getTemplateImageCornerParameter(Map<String, ProcessingImageDataContainer> convertMap) {
        Map<String, String[]> imageFilePathWithCornerParameters = new HashMap<String, String[]>();
        String[] cornerParametersArray;
        ProcessingImageDataContainer imageDataContainer;
        CornerAlgorithmParameters cornerAlgorithmParameters;
        for (String filePath : convertMap.keySet()) {
            imageDataContainer = convertMap.get(filePath);
            cornerAlgorithmParameters = imageDataContainer.getCornerAlgorithmParameters();
            if (cornerAlgorithmParameters != null) {
                cornerParametersArray = new String[4];
                cornerParametersArray[0] = new Float(cornerAlgorithmParameters.getKappa()).toString();
                cornerParametersArray[1] = cornerAlgorithmParameters.getMinMeasuer() + "";
                cornerParametersArray[2] = cornerAlgorithmParameters.getMinDistance() + "";
                cornerParametersArray[3] = cornerAlgorithmParameters.getIterationNumber() + "";
                imageFilePathWithCornerParameters.put(filePath, cornerParametersArray);
            }
        }
        return imageFilePathWithCornerParameters;
    }

    private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
        applicationData.setLastFilePath(lastOpenedFilePath);
        applicationData.setInputImageFilePathWitThresholdMap(
                convertMapWithFilePathAndProcessImageDataContainerInToStorableFormat(
                        inputImageFilePathAndItsDataContainerMap));
        applicationData.setTemplateImageFilePathWitThresholdMap(
                convertMapWithFilePathAndProcessImageDataContainerInToStorableFormat(
                        templateImageFilePathAndItsDataContainerMap),
                getTemplateImageCornerParameter(templateImageFilePathAndItsDataContainerMap));
        applicationData.storeApplicationConfig();
    }//GEN-LAST:event_formWindowClosing

    private void addTemplateImageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addTemplateImageButtonActionPerformed
        try {
            File file = loadImageFileFromFileSystem();
            addTemplateImage(file);
        } catch (IOException ex) {
            showErrorDialog("Ошибка при открытии шаблонного изображения!");
        }
    }//GEN-LAST:event_addTemplateImageButtonActionPerformed

    private void openTemplateImageMIActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openTemplateImageMIActionPerformed
        try {
            File file = loadImageFileFromFileSystem();
            addTemplateImage(file);
        } catch (IOException ex) {
            showErrorDialog("Ошибка при открытии шаблонного изображения!");
        }
    }//GEN-LAST:event_openTemplateImageMIActionPerformed

    private void removeTemplateImageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeTemplateImageButtonActionPerformed
        removeTemplateImage();
    }//GEN-LAST:event_removeTemplateImageButtonActionPerformed

    private void addInputImageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addInputImageButtonActionPerformed
        try {
            File file = loadImageFileFromFileSystem();
            if (file != null) {
                addInputImage(file);
            }
        } catch (IOException ex) {
            showErrorDialog("Ошибка при открытии изображения для распознования!");
        }
    }//GEN-LAST:event_addInputImageButtonActionPerformed

    private void removeInputImageButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeInputImageButtonActionPerformed
        removeInputImage();
    }//GEN-LAST:event_removeInputImageButtonActionPerformed

    private void isNeedUseEdgeAlgorithmActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_isNeedUseEdgeAlgorithmActionPerformed
        JCheckBox isNeedUseEdgeAlgorithmCheckBox = (JCheckBox) evt.getSource();
        if (isNeedUseEdgeAlgorithmCheckBox.isSelected()) {

            thresholdSlider.setEnabled(true);

            ThresholdEdgeAlgorithmData thresholdEdgeAlgorithmData = displayedImageProcessDataContainer.getThresholdEdgeAlgorithmData();
            int threshold;
            if (thresholdEdgeAlgorithmData != null) {
                threshold = thresholdEdgeAlgorithmData.getThreshold();
            } else {
                BufferedImage inputImage = (BufferedImage) displayedImageProcessDataContainer.getInputImage();
                ImageUInt8 gray = ConvertBufferedImage.convertFromSingle(inputImage, null, ImageUInt8.class);
                threshold = (int) GImageStatistics.mean(gray);
                displayedImageProcessDataContainer.setThresholdEdgeAlgorithmData(new ThresholdEdgeAlgorithmData(threshold));
            }

            thresholdSlider.setValue(threshold);
        } else {
            IconWithDescription iconWithDescription =
                    (IconWithDescription) inputImageList.getSelectedValue();
            ProcessingImageDataContainer inputImageData = inputImageFilePathAndItsDataContainerMap.get(iconWithDescription.getDescription());
            inputImageData.setEdgeInputImage(null);
            inputImageData.setThresholdEdgeAlgorithmData(null);

            thresholdSlider.setEnabled(false);
            thresholdSlider.setValue(0);
            edgeImageLabel.setIcon(null);
        }
    }//GEN-LAST:event_isNeedUseEdgeAlgorithmActionPerformed

    private void thresholdSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_thresholdSliderStateChanged
        JSlider source = (JSlider) evt.getSource();
        if (!source.getValueIsAdjusting()) {
            final int threshold = source.getValue();
//            SwingUtilities.invokeLater(new Runnable() {
//
//                public void run() {
            if (displayedImageProcessDataContainer != null) {

                ThresholdEdgeAlgorithmData thresholdEdgeAlgorithmData = displayedImageProcessDataContainer.getThresholdEdgeAlgorithmData();

                if (isNeedUseEdgeAlgorithm.isEnabled() && (thresholdEdgeAlgorithmData != null)) {
                    thresholdEdgeAlgorithmData.setThreshold(threshold);
//                    BufferedImage edgeImageOfInputImage = createEdgeImageFromInputImageByThreshold(
//                            (BufferedImage) displayedImageProcessDataContainer.getInputImage(),
//                            threshold);

                    BufferedImage edgeImageOfInputImage = binaryExample(
                            (BufferedImage) displayedImageProcessDataContainer.getInputImage(),
                            threshold);
                    displayedImageProcessDataContainer.setEdgeInputImage(edgeImageOfInputImage);
                    edgeImageLabel.setIcon(new ImageIcon(edgeImageOfInputImage));
                }
            }
            histogramThresholdPanel.setThreshold(threshold, true);
            histogramThresholdPanel.repaint();

//                }
//            });
        }
    }//GEN-LAST:event_thresholdSliderStateChanged

    private void upperThresholdSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_upperThresholdSliderStateChanged
    }//GEN-LAST:event_upperThresholdSliderStateChanged

    private void lowerThresholdSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_lowerThresholdSliderStateChanged
    }//GEN-LAST:event_lowerThresholdSliderStateChanged

    private void inputImageListSelectionChanged(ListSelectionEvent event) {
        ListSelectionModel lsm = (ListSelectionModel) event.getSource();

        edgeImageLabel.setIcon(null);
        isNeedUseEdgeAlgorithm.setEnabled(false);
        isNeedUseEdgeAlgorithm.setSelected(false);
        histogramThresholdPanel.clearHistogramm();
        thresholdSlider.setEnabled(false);
        thresholdSlider.setValue(0);

        if (!lsm.isSelectionEmpty()) {
            // Find out which indexes are selected.
            int minIndex = lsm.getMinSelectionIndex();
            int maxIndex = lsm.getMaxSelectionIndex();
            for (int i = minIndex; i <= maxIndex; i++) {
                if (lsm.isSelectedIndex(i)) {
                    IconWithDescription iconWithDescription =
                            (IconWithDescription) inputImageList.getModel().getElementAt(i);
                    ProcessingImageDataContainer inputImageData = inputImageFilePathAndItsDataContainerMap.get(iconWithDescription.getDescription());

                    BufferedImage inputImage = (BufferedImage) inputImageData.getInputImage();
                    inputImageLabel.setIcon(new ImageIcon(inputImage));
                    BufferedImage searchResultImage = (BufferedImage) inputImageData.getSearchResultImage();
                    if (searchResultImage != null) {
                        resultImageLabel.setIcon(new ImageIcon(searchResultImage));
                    } else {
                        resultImageLabel.setIcon(null);
                    }
                    if (inputImageData.getCornerImage() != null) {
                        BufferedImage cornerImage = (BufferedImage) inputImageData.getCornerImage();
                        ResampleOp resizeImage = new ResampleOp(cornerImage.getWidth() * 3, cornerImage.getHeight() * 3);
                        resampleOp.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal);
                        cornerLabel.setIcon(new ImageIcon(resizeImage.filter(cornerImage, null)));
                    } else {
                        cornerLabel.setIcon(null);
                    }


                    ImageUInt8 gray = ConvertBufferedImage.convertFromSingle(inputImage, null, ImageUInt8.class);
                    histogramThresholdPanel.update(gray);

                    displayedImageProcessDataContainer = inputImageData;

                    isNeedUseEdgeAlgorithm.setEnabled(true);
                    if (inputImageData.getThresholdEdgeAlgorithmData() != null) {
                        isNeedUseEdgeAlgorithm.setSelected(true);
                        thresholdSlider.setEnabled(true);
                        thresholdSlider.setValue(inputImageData.getThresholdEdgeAlgorithmData().getThreshold());
                    } else {
                        isNeedUseEdgeAlgorithm.setSelected(false);
                    }
                    calculateCorner.setEnabled(false);
                }
            }
        } else {
            inputImageLabel.setIcon(null);
            resultImageLabel.setIcon(null);
            cornerLabel.setIcon(null);
            displayedImageProcessDataContainer = null;
        }
        histogramThresholdPanel.repaint();
    }

    private void templateImageListSelectionChanged(ListSelectionEvent event) {
        ListSelectionModel lsm = (ListSelectionModel) event.getSource();

        edgeImageLabel.setIcon(null);
        isNeedUseEdgeAlgorithm.setEnabled(false);
        isNeedUseEdgeAlgorithm.setSelected(false);
        histogramThresholdPanel.clearHistogramm();
        thresholdSlider.setEnabled(false);
        thresholdSlider.setValue(0);

        if (!lsm.isSelectionEmpty()) {
            // Find out which indexes are selected.
            int minIndex = lsm.getMinSelectionIndex();
            int maxIndex = lsm.getMaxSelectionIndex();
            for (int i = minIndex; i <= maxIndex; i++) {
                if (lsm.isSelectedIndex(i)) {
                    IconWithDescription iconWithDescription =
                            (IconWithDescription) templateImageList.getModel().getElementAt(i);
                    ProcessingImageDataContainer inputImageData = templateImageFilePathAndItsDataContainerMap.get(iconWithDescription.getDescription());

                    BufferedImage inputImage = (BufferedImage) inputImageData.getInputImage();
                    inputImageLabel.setIcon(new ImageIcon(inputImage));
                    resultImageLabel.setIcon(null);

                    if (inputImageData.getCornerImage() != null) {
                        BufferedImage cornerImage = (BufferedImage) inputImageData.getCornerImage();
                        ResampleOp resizeImage = new ResampleOp(cornerImage.getWidth() * 3, cornerImage.getHeight() * 3);
                        resampleOp.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal);
                        cornerLabel.setIcon(new ImageIcon(resizeImage.filter(cornerImage, null)));
                    } else {
                        cornerLabel.setIcon(null);
                    }

                    ImageUInt8 gray = ConvertBufferedImage.convertFromSingle(inputImage, null, ImageUInt8.class);
                    histogramThresholdPanel.update(gray);

                    displayedImageProcessDataContainer = inputImageData;

                    isNeedUseEdgeAlgorithm.setEnabled(true);
                    if (inputImageData.getThresholdEdgeAlgorithmData() != null) {
                        isNeedUseEdgeAlgorithm.setSelected(true);
                        thresholdSlider.setEnabled(true);
                        thresholdSlider.setValue(inputImageData.getThresholdEdgeAlgorithmData().getThreshold());
                    } else {
                        isNeedUseEdgeAlgorithm.setSelected(false);
                    }
                    calculateCorner.setEnabled(true);
                }
            }
        } else {
            inputImageLabel.setIcon(null);
            resultImageLabel.setIcon(null);
            displayedImageProcessDataContainer = null;
            calculateCorner.setEnabled(false);
        }
        histogramThresholdPanel.repaint();
    }

    private void edgeAlgorithmTypeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_edgeAlgorithmTypeComboBoxActionPerformed
//        JComboBox edgeAlgorithmTypeComboBox = (JComboBox) evt.getSource();
//        String type = (String) edgeAlgorithmTypeComboBox.getSelectedItem();
//        if ("Пороговый".equals(type)) {
//            CardLayout edgeAlgorithmParametersLayout =
//                    (CardLayout) edgeDetectorsAlgorimthParametersPanel.getLayout();
//            edgeAlgorithmParametersLayout.show(edgeDetectorsAlgorimthParametersPanel, "thresholdAlgorithm");
//        }
//        if ("Канни".equals(type)) {
//            CardLayout edgeAlgorithmParametersLayout =
//                    (CardLayout) edgeDetectorsAlgorimthParametersPanel.getLayout();
//            edgeAlgorithmParametersLayout.show(edgeDetectorsAlgorimthParametersPanel, "cannyAlgorithm");
//        }
    }//GEN-LAST:event_edgeAlgorithmTypeComboBoxActionPerformed

    private void sourceTabbedPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_sourceTabbedPaneStateChanged
        JTabbedPane sourceTabbedPane = (JTabbedPane) evt.getSource();
        int selectedIndex = sourceTabbedPane.getSelectedIndex();
        if (selectedIndex == 0) {
            if (!inputImageList.isSelectionEmpty()) {
                int inputImageSelectedIndex = inputImageList.getSelectedIndex();
                inputImageList.clearSelection();
                inputImageList.setSelectedIndex(inputImageSelectedIndex);
            }
        } else {
            if (selectedIndex == 1) {
                if (!templateImageList.isSelectionEmpty()) {
                    int templateImageSelectedIndex = templateImageList.getSelectedIndex();
                    templateImageList.clearSelection();
                    templateImageList.setSelectedIndex(templateImageSelectedIndex);
                }
            }
        }
    }//GEN-LAST:event_sourceTabbedPaneStateChanged

    private void algorithmComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_algorithmComboBoxActionPerformed
        JComboBox algorithmChooserComboBox = (JComboBox) evt.getSource();
        String value = (String) algorithmChooserComboBox.getSelectedItem();
        CardLayout algorithmParametersLayout = (CardLayout) algorithmParametersPanel.getLayout();
        if ("HD".equals(value)) {
            algorithmParametersLayout.show(algorithmParametersPanel, "hdAlgorithmParameters");
        }
        if ("M-HD".equals(value)) {
            algorithmParametersLayout.show(algorithmParametersPanel, "m_hdAlgorithmParameters");
        }
        if ("NHD".equals(value)) {
            algorithmParametersLayout.show(algorithmParametersPanel, "greyImageHDAlgorithmParameters");
        }
        if ("SWHD".equals(value)) {
            algorithmParametersLayout.show(algorithmParametersPanel, "weightCornerHDAlgorithm");
        }
    }//GEN-LAST:event_algorithmComboBoxActionPerformed

    private void kSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_kSpinnerStateChanged
        float k = (Float) kSpinner.getValue();
        harrisCornerDetector.setGaussiansigma(k);
        if (displayedImageProcessDataContainer != null) {
            BufferedImage edgeImage = (BufferedImage) displayedImageProcessDataContainer.getEdgeInputImage();
            BufferedImage cornerImage = harrisCornerDetector.process(edgeImage);
            displayedImageProcessDataContainer.setCornerImage(cornerImage);
            displayedImageProcessDataContainer.setCorners(harrisCornerDetector.lastProcessResult());
            int minMeasuer = (Integer) minMeasuerSpinner.getValue();
            int minDistance = (Integer) minDistanceSpinner.getValue();
            int iterationNumber = (Integer) iterationSpinner.getValue();
            CornerAlgorithmParameters cornerAlgorithmParameters = new CornerAlgorithmParameters(iterationNumber, k, minDistance, minMeasuer);
            displayedImageProcessDataContainer.setCornerAlgorithmParameters(cornerAlgorithmParameters);
            ResampleOp resizeImage = new ResampleOp(cornerImage.getWidth() * 3, cornerImage.getHeight() * 3);
//            resizeImage.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal);
            cornerLabel.setIcon(new ImageIcon(resizeImage.filter(cornerImage, null)));
        }
    }//GEN-LAST:event_kSpinnerStateChanged

    private void minMeasuerSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_minMeasuerSpinnerStateChanged
        int minMeasuer = (Integer) minMeasuerSpinner.getValue();
        harrisCornerDetector.setMinMeasure(minMeasuer);
        if (displayedImageProcessDataContainer != null) {
            BufferedImage edgeImage = (BufferedImage) displayedImageProcessDataContainer.getEdgeInputImage();
            BufferedImage cornerImage = harrisCornerDetector.process(edgeImage);
            displayedImageProcessDataContainer.setCornerImage(cornerImage);
            displayedImageProcessDataContainer.setCorners(harrisCornerDetector.lastProcessResult());
            float k = (Float) kSpinner.getValue();
            int minDistance = (Integer) minDistanceSpinner.getValue();
            int iterationNumber = (Integer) iterationSpinner.getValue();
            CornerAlgorithmParameters cornerAlgorithmParameters = new CornerAlgorithmParameters(iterationNumber, k, minDistance, minMeasuer);
            displayedImageProcessDataContainer.setCornerAlgorithmParameters(cornerAlgorithmParameters);
            ResampleOp resizeImage = new ResampleOp(cornerImage.getWidth() * 3, cornerImage.getHeight() * 3);
//            resizeImage.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal);
            cornerLabel.setIcon(new ImageIcon(resizeImage.filter(cornerImage, null)));
        }
    }//GEN-LAST:event_minMeasuerSpinnerStateChanged

    private void minDistanceSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_minDistanceSpinnerStateChanged
        int minDistance = (Integer) minDistanceSpinner.getValue();
        harrisCornerDetector.setMinDistance(minDistance);
        if (displayedImageProcessDataContainer != null) {
            BufferedImage edgeImage = (BufferedImage) displayedImageProcessDataContainer.getEdgeInputImage();
            BufferedImage cornerImage = harrisCornerDetector.process(edgeImage);
            displayedImageProcessDataContainer.setCornerImage(cornerImage);
            displayedImageProcessDataContainer.setCorners(harrisCornerDetector.lastProcessResult());
            float k = (Float) kSpinner.getValue();
            int minMeasuer = (Integer) minMeasuerSpinner.getValue();
            int iterationNumber = (Integer) iterationSpinner.getValue();
            CornerAlgorithmParameters cornerAlgorithmParameters = new CornerAlgorithmParameters(iterationNumber, k, minDistance, minMeasuer);
            displayedImageProcessDataContainer.setCornerAlgorithmParameters(cornerAlgorithmParameters);
            ResampleOp resizeImage = new ResampleOp(cornerImage.getWidth() * 3, cornerImage.getHeight() * 3);
//            resizeImage.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal);
            cornerLabel.setIcon(new ImageIcon(resizeImage.filter(cornerImage, null)));
        }
    }//GEN-LAST:event_minDistanceSpinnerStateChanged

    private void iterationSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_iterationSpinnerStateChanged
        int iterationNum = (Integer) iterationSpinner.getValue();
        harrisCornerDetector.setPiramidi(iterationNum);
        if (displayedImageProcessDataContainer != null) {
            BufferedImage edgeImage = (BufferedImage) displayedImageProcessDataContainer.getEdgeInputImage();
            BufferedImage cornerImage = harrisCornerDetector.process(edgeImage);
            displayedImageProcessDataContainer.setCornerImage(cornerImage);
            displayedImageProcessDataContainer.setCorners(harrisCornerDetector.lastProcessResult());
            float k = (Float) kSpinner.getValue();
            int minMeasuer = (Integer) minMeasuerSpinner.getValue();
            int minDistance = (Integer) minDistanceSpinner.getValue();
            CornerAlgorithmParameters cornerAlgorithmParameters = new CornerAlgorithmParameters(iterationNum, k, minDistance, minMeasuer);
            displayedImageProcessDataContainer.setCornerAlgorithmParameters(cornerAlgorithmParameters);
            ResampleOp resizeImage = new ResampleOp(cornerImage.getWidth() * 3, cornerImage.getHeight() * 3);
//            resizeImage.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal);
            cornerLabel.setIcon(new ImageIcon(resizeImage.filter(cornerImage, null)));
        }
    }//GEN-LAST:event_iterationSpinnerStateChanged

    private void calculateCornerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_calculateCornerActionPerformed
        float k = (Float) kSpinner.getValue();
        harrisCornerDetector.setGaussiansigma(k);
        int minMeasuer = (Integer) minMeasuerSpinner.getValue();
        harrisCornerDetector.setMinMeasure(minMeasuer);
        int minDistance = (Integer) minDistanceSpinner.getValue();
        harrisCornerDetector.setMinDistance(minDistance);
        int iterationNum = (Integer) iterationSpinner.getValue();
        harrisCornerDetector.setPiramidi(iterationNum);
        if (displayedImageProcessDataContainer != null) {
            BufferedImage edgeImage = (BufferedImage) displayedImageProcessDataContainer.getEdgeInputImage();
            BufferedImage cornerImage = harrisCornerDetector.process(edgeImage);
            displayedImageProcessDataContainer.setCornerImage(cornerImage);
            displayedImageProcessDataContainer.setCorners(harrisCornerDetector.lastProcessResult());
            CornerAlgorithmParameters cornerAlgorithmParameters = new CornerAlgorithmParameters(iterationNum, k, minDistance, minMeasuer);
            displayedImageProcessDataContainer.setCornerAlgorithmParameters(cornerAlgorithmParameters);
            ResampleOp resizeImage = new ResampleOp(cornerImage.getWidth() * 3, cornerImage.getHeight() * 3);
            cornerLabel.setIcon(new ImageIcon(resizeImage.filter(cornerImage, null)));
        }

    }//GEN-LAST:event_calculateCornerActionPerformed

    private void addFolderWithInputImageActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addFolderWithInputImageActionPerformed
        try {
            File file = loadImageDirectoryFileFromFileSystem();
            if (file != null) {
                for (File imageFile : file.listFiles()) {
                    addInputImage(imageFile);
                }
            }
        } catch (IOException ex) {
            showErrorDialog("Ошибка при открытии изображения для распознования!");
        }
    }//GEN-LAST:event_addFolderWithInputImageActionPerformed

    private void addFolderWithTemplateImageActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addFolderWithTemplateImageActionPerformed
        try {
            File file = loadImageDirectoryFileFromFileSystem();
            if (file != null) {
                for (File imageFile : file.listFiles()) {
                    addTemplateImage(imageFile);
                }
            }
        } catch (IOException ex) {
            showErrorDialog("Ошибка при открытии изображения для распознования!");
        }
    }//GEN-LAST:event_addFolderWithTemplateImageActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {

        /*
         * Set the look and feel
         */
        try {
            LOGGER.debug("Установка Look and Feel.");
            javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getCrossPlatformLookAndFeelClassName());
        } catch (ClassNotFoundException ex) {
            LOGGER.error("Исключение на этапе установки Look and Feel.", ex);
        } catch (InstantiationException ex) {
            LOGGER.error("Исключение на этапе установки Look and Feel.", ex);
        } catch (IllegalAccessException ex) {
            LOGGER.error("Исключение на этапе установки Look and Feel.", ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            LOGGER.error("Исключение на этапе установки Look and Feel.", ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new MainForm().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton addFolderWithInputImage;
    private javax.swing.JButton addFolderWithTemplateImage;
    private javax.swing.JButton addInputImageButton;
    private javax.swing.JButton addTemplateImageButton;
    private javax.swing.JPanel algorithmChooserPanel;
    private javax.swing.JComboBox algorithmComboBox;
    private javax.swing.JPanel algorithmPanel;
    private javax.swing.JPanel algorithmParametersPanel;
    private javax.swing.JPanel algorithmsPanel;
    private javax.swing.JSplitPane baseSplitPane;
    private javax.swing.JPanel borderImageCalculatorPanel;
    private javax.swing.JButton calculateButton;
    private javax.swing.JButton calculateCorner;
    private javax.swing.JPanel calculatePanel;
    private javax.swing.JTabbedPane calculateTabbedPane;
    private javax.swing.JPanel calculatingPanel;
    private javax.swing.JLabel calculationThresholdLabel;
    private javax.swing.JPanel calculationThresholdPanel;
    private javax.swing.JSpinner calculationThresholdSpinner;
    private javax.swing.JPanel cannyAlgorithmPanel;
    private javax.swing.JPanel cannyHistogramConstainerPanel;
    private javax.swing.JLabel cannyHistogrammLabel;
    private javax.swing.JPanel computationResultPanel;
    private javax.swing.JLabel cornerLabel;
    private javax.swing.JScrollPane cornerScrollPane;
    private javax.swing.JPanel cornerSearchPanel;
    private javax.swing.JPanel cornerWeightHDAlgorithmParameters;
    private javax.swing.JPanel edgeAlgorimthUsageChechBox;
    private javax.swing.JPanel edgeAlgorithmChooserPanel;
    private javax.swing.JComboBox edgeAlgorithmTypeComboBox;
    private javax.swing.JPanel edgeDetectorsAlgorimthParametersPanel;
    private javax.swing.JLabel edgeImageLabel;
    private javax.swing.JScrollPane edgeScrollPane;
    private javax.swing.JMenuItem exitMI;
    private javax.swing.JMenu fileMenu;
    private javax.swing.Box.Filler filler1;
    private javax.swing.Box.Filler filler10;
    private javax.swing.Box.Filler filler11;
    private javax.swing.Box.Filler filler12;
    private javax.swing.Box.Filler filler15;
    private javax.swing.Box.Filler filler2;
    private javax.swing.Box.Filler filler3;
    private javax.swing.Box.Filler filler4;
    private javax.swing.Box.Filler filler5;
    private javax.swing.Box.Filler filler6;
    private javax.swing.Box.Filler filler7;
    private javax.swing.Box.Filler filler8;
    private javax.swing.JPanel greyImageHDAlgorithmParameters;
    private javax.swing.JPanel hdAlgorithmParameters;
    private javax.swing.JPanel histogramContainerPanel;
    private javax.swing.JLabel histogrammLabel;
    private javax.swing.JSplitPane inputDataSplitPane;
    private javax.swing.JLabel inputImageLabel;
    private javax.swing.JList inputImageList;
    private javax.swing.JPanel inputImagePanel;
    private javax.swing.JScrollPane inputImageScrollPane;
    private javax.swing.JTabbedPane inputImageTabbedPanel;
    private javax.swing.JPanel inputImagesControlPanel;
    private javax.swing.JPanel inputImagesPanel;
    private javax.swing.JScrollPane inputImagesScrollPane;
    private javax.swing.JPanel inputPanel;
    private javax.swing.JCheckBox isNeedUseEdgeAlgorithm;
    private javax.swing.JLabel iterationLabel;
    private javax.swing.JPanel iterationParameter;
    private javax.swing.JSpinner iterationSpinner;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JLabel kLable;
    private javax.swing.JSpinner kSpinner;
    private javax.swing.JPanel kappaParameter;
    private javax.swing.JSlider lowerThresholdSlider;
    private javax.swing.JLabel lowerThresholdSliderLabel;
    private javax.swing.JPanel m_hdAlgorithmParameters;
    private javax.swing.JSpinner m_hdThresholdParameter;
    private javax.swing.JLabel m_hdThresholdParameterLabel;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JLabel minDistanceLabel;
    private javax.swing.JPanel minDistanceParameter;
    private javax.swing.JSpinner minDistanceSpinner;
    private javax.swing.JLabel minMeasuerLabel;
    private javax.swing.JPanel minMeasuerParameter;
    private javax.swing.JSpinner minMeasuerSpinner;
    private javax.swing.JMenuItem openImageMI;
    private javax.swing.JMenuItem openTemplateImageMI;
    private javax.swing.JScrollPane relustImageScrollPane;
    private javax.swing.JButton removeInputImageButton;
    private javax.swing.JButton removeTemplateImageButton;
    private javax.swing.JLabel resultImageLabel;
    private javax.swing.JScrollPane resultsScrollPane;
    private javax.swing.JTextArea resultsTextArea;
    private javax.swing.JPanel sourcePane;
    private javax.swing.JTabbedPane sourceTabbedPane;
    private javax.swing.JList templateImageList;
    private javax.swing.JPanel templateImagesControlPanel;
    private javax.swing.JPanel templateImagesPanel;
    private javax.swing.JScrollPane templateImagesScrollPane;
    private javax.swing.JPanel thresholdAlgorithmPanel;
    private javax.swing.JPanel thresholdHistogrammContainer;
    private javax.swing.JLabel thresholdLabel;
    private javax.swing.JSlider thresholdSlider;
    private javax.swing.JPanel thresholdSliderContainer;
    private javax.swing.JSlider upperThresholdSlider;
    private javax.swing.JLabel upperThresholdSliderLabel;
    private javax.swing.JSpinner weightCornerImportants;
    private javax.swing.JSpinner weightCornerRadius;
    // End of variables declaration//GEN-END:variables
}
